/*
 * Copyright Hundsun Technologies Inc. All Rights Reserved.
 */

package common

import (
	"sync"

	"hundsun.com/hsl/hschain/protos"
	"hundsun.com/hsl/hschain/protos/common"
)

// SharedMiners 多个goroutine之间共享的Miners
type SharedMiners struct {
	sync.RWMutex
	size  int
	data  map[protos.Address]*common.Miner
	index map[protos.Address]int
}

// Add 添加一个Miner
func (s *SharedMiners) Add(m *common.Miner) {
	s.Lock()
	defer s.Unlock()
	if s.data == nil {
		s.data = make(map[protos.Address]*common.Miner, MaxMinersCount)
		s.index = make(map[protos.Address]int, MaxMinersCount)
	}
	if len(s.data) < MaxMinersCount {
		s.data[protos.Address(m.Address)] = m
		s.index[protos.Address(m.Address)] = s.size
		s.size++
	}
}

// Remove 删除指定Miner
func (s *SharedMiners) Remove(address protos.Address) bool {
	s.Lock()
	defer s.Unlock()
	idx, ok := s.index[address]
	if !ok {
		return false
	}
	delete(s.data, address)
	for k, v := range s.index {
		if v > idx {
			s.index[k] = v - 1
		}
	}
	s.size--
	return true
}

// IndexOf 查找指定矿工，找不到则返回-1
func (s *SharedMiners) IndexOf(address protos.Address) int {
	s.RLock()
	defer s.RUnlock()
	idx, ok := s.index[address]
	if ok {
		return idx
	}
	return -1
}

// ReplaceAll 删除用给定的miners替换已有的miners
func (s *SharedMiners) ReplaceAll(miners []*common.Miner) {
	s.Lock()
	defer s.Unlock()
	if s.data == nil {
		s.data = make(map[protos.Address]*common.Miner, MaxMinersCount)
		s.index = make(map[protos.Address]int, MaxMinersCount)
	}
	for i, m := range miners {
		if len(s.data) >= MaxMinersCount {
			break
		}
		s.data[protos.Address(m.Address)] = m
		s.index[protos.Address(m.Address)] = i
	}
	s.size = len(s.data)
}

// Miners 返回miners
func (s *SharedMiners) Miners() map[protos.Address]*common.Miner {
	s.RLock()
	defer s.RUnlock()
	result := make(map[protos.Address]*common.Miner, len(s.data))
	for k, m := range s.data {
		result[k] = m
	}
	return result
}
